package com.veeder.datacollection.collector;


import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.veeder.datacollection.config.*;
import com.veeder.datacollection.exception.ConfigurationException;
import com.veeder.datacollection.rs232.RS232CommandExecutor;
import com.veeder.datacollection.rs232.response.*;

public abstract class ATGFetcher {

	protected final Logger logger;

	public ATGFetcher() {
		this.logger = Logger.getLogger(this.getClass().getName());
		logger.setUseParentHandlers(true);
	}

	public abstract ConnectionParam getConnectionParam();

	/*
	 * a latest inventory rawMessage record. return null when connection failed.
	 */
	public abstract String getLatestInventory();

	public abstract TankResponseReport<BasicTankInventory> getAllTankInventories();

	public abstract Boolean getTankConfigFromATG(int tankId);

	public abstract Float getTankProbeOffsetFromATG(int tankId);

	public abstract Float getTankDiameterFromATG(int tankId);

	public abstract Float getTankCapacityFromATG(int tankId);

	public abstract Float getTankCoefficientFromATG(int tankId);

	public abstract Float getTankTiltFromATG(int tankId);

	public abstract Float getTankProbeFloatSizeFromATG(int tankId);

	public abstract TankChart getTankChartFromATG(int tankId);

	public abstract AlarmList getActiveAlarmListFromATG();

	public abstract String getTankProductNoFromATG(int tankId);
	

	public Boolean getTankConfig(TankParam param) {
		return getTankConfigFromATG(param.getTankId());
	}

	public Float getTankProbeOffset(TankParam param) {
		return getTankProbeOffsetFromATG(param.getTankId());
	}

	public Float getTankDiameter(TankParam param) {
		Float result = null;
		String configed = param.getDiameter();
		if (configed != null) {
			if (configed.equalsIgnoreCase("auto")) {
				result = getTankDiameterFromATG(param.getTankId());
			} else {
				try {
					result = Float.parseFloat(configed);
				} catch (Exception e) {
					logger.log(Level.WARNING, "parse diameter error: " + e.toString());
				}
			}
		}

		return result;
	}

	public Float getTankCapacity(TankParam param) {
		Float result = null;
		String configed = param.getCapacity();
		if (configed != null) {
			if (configed.equalsIgnoreCase("auto")) {
				result = getTankCapacityFromATG(param.getTankId());
			} else {
				try {
					result = Float.parseFloat(configed);
				} catch (Exception e) {
					logger.log(Level.WARNING, "parse capacity error: " + e.toString());
				}
			}
		}

		return result;
	}

	public Float getTankCoefficient(TankParam param) {
		Float result = null;
		String configed = param.getCoefficient();
		if (configed != null) {
			if (configed.equalsIgnoreCase("auto")) {
				result = getTankCoefficientFromATG(param.getTankId());
			} else {
				try {
					result = Float.parseFloat(configed);
				} catch (Exception e) {
					logger.log(Level.WARNING, "parse coefficient error: " + e.toString());
				}
			}
		}

		return result;
	}

	public Float getTankTilt(TankParam param) {
		return getTankTiltFromATG(param.getTankId());
	}

	public Float getTankProbeFloatSize(TankParam param) {
		return getTankProbeFloatSizeFromATG(param.getTankId());
	}

	public TankChart getTankChart(TankParam param) {
		TankChart result = null;
		String configed = param.getTankChart();

		if (configed != null) {
			if (configed.equalsIgnoreCase("auto")) {
				result = getTankChartFromATG(param.getTankId());
			} else {
				try {
					result = new TankChart();
					result.setHeightVolumePairs(parseTankChart(configed));
				} catch (Exception e) {
					logger.log(Level.WARNING, "parse tankchart error: " + e.toString());
				}
			}
		}

		return result;
	}

	public String getTankProductNo(TankParam param) {
		String result = null;
		String configed = param.getProductNo();

		if (configed != null) {
			if (configed.equalsIgnoreCase("auto")) {
				result = getTankProductNoFromATG(param.getTankId());
			} else {
				result = param.getProductNo();
			}
		}

		return result;
	}

	/**
	 * 
	 * @param chartStr
	 * @return could be an empty set.
	 * @throws ConfigurationException
	 */
	private static TreeSet<HeightVolumePair> parseTankChart(String chartStr) throws ConfigurationException {
		TreeSet<HeightVolumePair> pairs = new TreeSet<HeightVolumePair>();
		if (chartStr != null) {
			StringTokenizer strTk = new StringTokenizer(chartStr, ";");
			while (strTk.hasMoreTokens()) {
				String str = strTk.nextToken();
				String[] pairArr = str.split(",");
				if (pairArr == null || pairArr.length != 2) {
					throw new ConfigurationException("tank chart config error, error place: " + str);
				} else {
					HeightVolumePair pair = new HeightVolumePair();
					pair.setHeight(Float.parseFloat(pairArr[0]));
					pair.setVolume(Float.parseFloat(pairArr[1]));
					pairs.add(pair);
				}
			}

		}
		return pairs;
	}
	
	public void closeConnectionWithATG() {
		RS232CommandExecutor.getInstance().closeConnection();
	}
}
